﻿#region COPYRIGHT© 2009-2012 Phillip Clark. All rights reserved.

// For licensing information see License.txt (MIT style licensing).

#endregion

using System.Threading;
using FlitBit.Core;

namespace FlitBit.Cache
{
	/// <summary>
	///   Cache stats collector that keeps a count.
	/// </summary>
	public class CountingCacheStatsCollector : Disposable, ICacheStatsCollector
	{
		int _attempts;
		int _evictions;
		int _expirations;
		int _hits;
		int _removes;
		int _writes;

		/// <summary>
		///   Creates a new instance.
		/// </summary>
		/// <param name="name"></param>
		public CountingCacheStatsCollector(string name)
		{
			this.Name = name;
		}

		/// <summary>
		///   Gets the cache's name.
		/// </summary>
		public string Name { get; private set; }

		/// <summary>
		///   Disposes the instance.
		/// </summary>
		/// <param name="disposing"></param>
		/// <returns></returns>
		protected override bool PerformDispose(bool disposing)
		{
			return true;
		}

		#region ICacheStatsCollector Members

		/// <summary>
		///   Increments the number of hits.
		/// </summary>
		/// <param name="count">the increment</param>
		public void IncrementHits(int count)
		{
			Interlocked.Add(ref _hits, count);
		}

		/// <summary>
		///   Increments the number of read attempts.
		/// </summary>
		public virtual void IncrementReadAttempts()
		{
			Interlocked.Increment(ref _attempts);
		}

		/// <summary>
		///   Increments the number of writes.
		/// </summary>
		public void IncrementWrites()
		{
			Interlocked.Increment(ref _writes);
		}

		/// <summary>
		///   Increments the number of removes.
		/// </summary>
		public void IncrementRemoves()
		{
			Interlocked.Increment(ref _removes);
		}

		/// <summary>
		///   Increments the number of expirations.
		/// </summary>
		public void IncrementExpired()
		{
			Interlocked.Increment(ref _expirations);
		}

		/// <summary>
		///   Increments the number of evictions.
		/// </summary>
		public void IncrementEvictions()
		{
			Interlocked.Increment(ref _evictions);
		}

		/// <summary>
		///   Increments the number of evictions.
		/// </summary>
		/// <param name="count">increment</param>
		public void IncrementEvictions(int count)
		{
			Interlocked.Add(ref _evictions, count);
		}

		/// <summary>
		///   Samples the stats.
		/// </summary>
		/// <returns></returns>
		public CacheStats Sample()
		{
			return new CacheStats(Name,
														Thread.VolatileRead(ref _attempts),
														Thread.VolatileRead(ref _expirations),
														Thread.VolatileRead(ref _evictions),
														Thread.VolatileRead(ref _hits),
														Thread.VolatileRead(ref _removes),
														Thread.VolatileRead(ref _writes)
				);
		}

		#endregion
	}
}